#ifndef __ano_h_
#define __ano_h_
#include "ano_init.h"
#include "stdbool.h"
#include "main.h"
#include "usart.h"
#ifndef __ARMCC_
#include "sys/_stdint.h"
#endif

/***
 * 协议结构
 * 帧头 源地址 目标地址 功能码 数据长度 数据内容 和校验 附加校验
 * HEAD |S_ADDR|D_ADDR|ID|LEN|DATA|SUM_CHECK|ADD_CHECK|
 * 1byte|1byte|1byte|1byte|2byte|nbyte|1byte|1byte|
 ***/
/*** ############   根据协议V8.06编写   ############ ***/
/*** ############ Hard ID Define Start ############ ***/


/***功能启用选择***/
/**#第一部分**/
#define Fly_Ctrl_Frames ANO_True      // 飞控相关信息 ID:0x01~0x0f
#define Fly_Ctrl_Output_Frames ANO_False // 飞控控制量输出 0x20~0x21
#define Fly_Ctrl_Rev_Frames ANO_False    // 飞控接受信息
#define Fly_CtrlRev_CMD_Frames ANO_False // 飞控接受命令
#define Optical_Flow_Frames ANO_False    // 光流信息
#define Stop_Route ANO_False             // 航点信息

/**#第二部分**/
#define CMD_Frames ANO_True // 命令帧

/**#第三部分**/
#define Read_Write_Frames ANO_True // 读写信息

/**#第四部分**/
#define Other_Frames ANO_True // 其他帧

/*** 定义部署的环境所用ID Enable EDIT ***/
#define LOCA_ID ANO_Fly_Ctrl
#define TARGET_ID ANO_Upper_Computer


/*********设置 命令/参数 数量**********/
#define cmd_number (4)//命令数量
#define param_number (3)//参数数量


/*填入结构体指针*/
/**
 * Ⅰ基本信息类帧
 */
#if Fly_Ctrl_Frames
/*
 * 1.飞控相关类
 * 注释相应的定义即可启用或关闭发送的数据
 * */
#define ID01 // 惯性传感器
#define ID02 // 罗盘、气压、温度传感器
#define ID03 // 飞控姿态：欧拉角
#define ID04 // 飞控姿态：四元数
#define ID05 // 高度数据
#define ID06 // 飞控运行模式
#define ID07 // 飞行速度数据
#define ID08 // 位置偏移数据
#define ID09 // 风速估计
#define ID0a // 目标姿态数据
#define ID0b // 目标速度数据
#define ID0c // 回航信息
#define ID0d // 电压电流数据
#define ID0e // 外界模块工作状态
#define ID0f // RGB亮度信息输出
#endif

#if Fly_Ctrl_Output_Frames
/*2.飞控控制量输出类*/
#define ID20 // PWM控制量
#define ID21 // 姿态控制量
#endif

#if Fly_Ctrl_Rev_Frames
/*3.飞控接受信息类*/
#define ID30 // GPS传感器1
#define ID31 // 原始光流信息
#define ID32 // 通用位置型传感器(非捷联载体测量型)
#define ID33 // 通用速度型传感器(捷联载体测量型)
#define ID34 // 通用测距型传感器(捷联载体测量型)
#define ID35 // 通用图像特征点信息帧
#endif

#if Fly_CtrlRev_CMD_Frames
/*4.飞控接受控制指令类*/
#define ID40 // 遥控器数据
#define ID41 // 实时控制帧
#endif

#if Optical_Flow_Frames
/*5.光流信息类*/
#define ID51 // 匿名光流数据
#endif

#if Stop_Route
/*6.GPS航点读写帧*/
#define ID60 // 航点读取
#define ID61 // 航点写入、航点读取返回
#endif

#if CMD_Frames
/**
 * Ⅱ功能触发类帧
 */
#define IDc0 // CMD命令帧
#define IDc1 // CMD功能帧
#define IDc2 // CMD命令信息帧
#endif

#if Read_Write_Frames
/**
 * Ⅲ参数读写类帧
 */
#define IDe0 //
#define IDe1 //
#define IDe3 //
#endif

#if Other_Frames
/**
 * Ⅳ其他帧
 */
#define IDa0 //
#define IDa1 //
#define IDb1 //
#define IDb2 //
#endif

/**
 * 匿名协议帧头结构体定义
 */

typedef const struct ano_head
{
    uint8_t head;
    uint8_t s_addr;
    uint8_t d_addr;
    uint8_t id;
    uint8_t len0;
    uint8_t len1;
    /* data */
} __packed ano_head_t;

typedef struct ano_tail
{
    uint8_t sc;
    uint8_t ac;
    /* data */
} __packed ano_tail_t;

/**
 *数据校验帧
 */
typedef struct ano00
{
    ano_head_t head;
    uint8_t id_get;
    uint8_t sc_get;
    uint8_t ac_get;
    ano_tail_t tail;
    /* data */
} __packed Check_t;

/***############飞控基本信息############***/

/**
 *惯性导航传感器数据
 */
typedef struct ano01
{
    ano_head_t head;
    int16_t acc_x;
    int16_t acc_y;
    int16_t acc_z;
    int16_t gyr_x;
    int16_t gyr_y;
    int16_t gyr_z;
    int8_t shock_sta;
    ano_tail_t tail;
    /* data */
} __packed Ins_t;

/**
 *地磁数据
 */
typedef struct ano02
{
    ano_head_t head;
    int16_t mag_x;
    int16_t mag_y;
    int16_t mag_z;
    int16_t tmp;
    uint8_t mag_sta;
    ano_tail_t tail;
    /* data */
} __packed Mag_t;

// 匿名上位机姿态角：欧拉角
// 扩大100倍
typedef struct ano03
{
    ano_head_t head;
    int16_t rol;
    int16_t pit;
    int16_t yaw;
    uint8_t fusion_sta;
    ano_tail_t tail;
    /* data */
} __packed Angle_t;

// 匿名上位机姿态角：四元数
// 传输时扩大10000倍
typedef struct ano04
{
    ano_head_t head;
    int16_t V0;
    int16_t V1;
    int16_t V2;
    uint16_t V3;
    uint8_t fusion_sta;
    ano_tail_t tail;
    /* data */
} __packed Quaternion_t;

// 高度数据
typedef struct ano05
{
    ano_head_t head;
    int32_t alt_bar; // 气压计高度
    int32_t alt_add; // 附加高度传感器高度
    int32_t alt_fu;  // 融合后对地高度
    uint8_t alt_sta; // 测距状态
    ano_tail_t tail;
} __packed Height_t;

// 飞控运行模式
typedef struct ano06
{
    ano_head_t head;
    uint8_t mode;  // 飞控模式
    uint8_t sflag; // 功能标志 0锁定 1解锁 2已起飞
    uint8_t cid;   // 当前飞控执行的指令功能 完成后复位为"悬停功能"
    uint8_t cmd0;
    uint8_t cmd1;
    ano_tail_t tail;
} __packed Fc_mode_t;

// 飞行数据速度
typedef struct ano07
{
    ano_head_t head;
    int16_t speed_x; // 各个轴上的运动速度 单位cm/s
    int16_t speed_y;
    int16_t speed_z;
    ano_tail_t tail;
    /* data */
} __packed Speed_t;

// 位置偏移数据信息
typedef struct ano08
{
    ano_head_t head;
    int32_t pos_x;
    int32_t pos_y;
    int32_t pos_z;
    ano_tail_t tail;
    /* data */
} __packed Position_Offset_t;

// 风速
typedef struct ano09
{
    ano_head_t head;
    int16_t wind_x; // cm/s
    int16_t wind_y;
    ano_tail_t tail;
    /* data */
} __packed Wind_speed_t;

// 目标姿态数据
typedef struct ano0a
{
    ano_head_t head;
    int16_t tar_rol;
    int16_t tar_pit;
    int16_t tar_yaw;
    ano_tail_t tail;
    /* data */
} __packed tar_att_t;

// 目标速度数据
typedef struct ano0b
{
    ano_head_t head;
    int16_t tar_spped_X;
    int16_t tar_spped_y;
    int16_t tar_spped_z;
    ano_tail_t tail;
    /* data */
} __packed tar_speed_t;

// 回航信息
typedef struct ano0c
{
    ano_head_t head;
    int16_t r_a; // 扩大10倍传输
    int16_t r_d;
    ano_tail_t tail;
    /* data */
} __packed RAD_t;

/**
 * 电压电流数据
 * 电压 需要扩大100倍
 * 电流 需要扩大100倍
 * */
typedef struct ano0d
{
    ano_head_t head;
    uint16_t votage;  // 电压 需要扩大100倍
    uint16_t current; // 电流 需要扩大100倍
    ano_tail_t tail;
    /* data */
} __packed Vbat_t;

/**
 * 外接模块工作状态
 * 0为无数据
 * 1为有数据但不可用
 * 2为正常
 * 3为良好(3为GPS专用)
 * */
typedef struct ano0e
{
    ano_head_t head;
    uint8_t votage;      // 通用速度传感器
    uint8_t current;     // 通用位置传感器
    uint8_t sta_gps;     // 传感器状态
    uint8_t sta_clt_add; // 附加测高状态器状态
    ano_tail_t tail;
    /* data */
} __packed extern_moude_sta_t;

/**
 * 亮度信息RGB灯的亮度
 */
typedef struct ano0f
{
    ano_head_t head;
    uint8_t bri_r;
    uint8_t bri_g;
    uint8_t bri_b;
    uint8_t bri_a;
    ano_tail_t tail;
    /* data */
} __packed bri_rgb_t;

/**************************************/
/***#############飞控输出类定义##########***/
/**************************************/

/**
 * PWM数据
 * */
typedef struct ano20
{
    ano_head_t head;
    uint16_t PWM1;
    uint16_t PWM2;
    uint16_t PWM3;
    uint16_t PWM4;
    uint16_t PWM5;
    uint16_t PWM6;
    uint16_t PWM7;
    uint16_t PWM8;
    ano_tail_t tail;
    /* data */
} __packed Pwm_t;

/**
 * 姿态控制量
 * xyz控制量为±5000
 * thr为0~10000
 * */
typedef struct ano21
{
    ano_head_t head;
    int16_t ctrl_rol;
    int16_t ctrl_pit;
    int16_t ctrl_yaw;
    int16_t ctrl_thr; // 油门控制量
    ano_tail_t tail;
    /* data */
} __packed att_ctrl_t;

/**************************************/
/***#############飞控接受类定义##########***/
/**************************************/

/**
 * 遥控器数据ID0x40*/
typedef struct ano40
{
    ano_head_t head;
    int16_t rol;
    int16_t pit;
    int16_t thr;
    int16_t yaw;
    int16_t aux1;
    int16_t aux2;
    int16_t aux3;
    int16_t aux4;
    int16_t aux5;
    int16_t aux6;
    ano_tail_t tail;
    /* data */
} __packed Rc_t;

/**************************************/
/***##########功能触发帧#############***/
/**************************************/

/**
 * cmd命令帧*/
typedef struct anoc0
{
    ano_head_t head;
    uint8_t cid0;
    uint8_t cid1;
    uint8_t cid2;

    uint8_t val0;
    uint8_t val1;
    uint8_t val2;
    uint8_t val3;
    uint8_t val4;
    uint8_t val5;
    uint8_t val6;
    uint8_t val7;

    ano_tail_t tail;
    /* data */
} __packed cmd_c0_t;

/**
 * cmd功能帧*/
typedef struct anoc1
{
    ano_head_t head;
    uint8_t cmd;
    uint16_t val;

    ano_tail_t tail;
    /* data */
} __packed cmd_c1_t;

/**
 * cmd命令信息帧
 *val = 0 无参数
 *    = 1 uint8_t
 *    = 2 int8_t
 *    = 3 uint16_t
 *    = 4 int16_t
 *    = 5 uint32_t
 *    = 6 int32_t
 *    = 7 uint64_t
 *    = 8 int64_t
 *    = 9 float
 *    = 10 double
 */
typedef struct anoc2
{
    ano_head_t head;

    uint16_t cmd_id; // 命令ID,代表是第几个命令
    struct c0
    {
        uint8_t cid0; // 该命令的CID
        uint8_t cid1;
        uint8_t cid2;

        uint8_t val0;
        uint8_t val1;
        uint8_t val2;
        uint8_t val3;
        uint8_t val4;
        uint8_t val5;
        uint8_t val6;
        uint8_t val7;
    } __packed cmd_c0_v;
    char cmd_name[20]; // 命令名称
    char cmd_info[50]; // 命令介绍

    ano_tail_t tail;
    /* data */
} __packed cmd_c2_t;

/**************************************/
/***##########参数读写类#############***/
/**************************************/

/// @brief 参数命令
/*
*
cmd = 0x00 读取设备信息 val无意义,等于0即可
=0x01 读取参数个数
=0x02 读取参数值 此时val为参数ID 下位机返回0xe1
=0x03 读取参数信息此时val为参数ID 下位机返回0xe2
cmd=0x10 val=0xaa 所有参数恢复默认值 下位机返回0x00
cmd=0x10 val=0xab 所有参数保存 下位机返回0x00
cmd=0x10 val=0x20 清除加速校准数据,校准开始会自动发送本命令雀斑上传的数据为传感器原始数据 下位机返回0x00
cmd=0x10 val=0x21 发送完加速度校准数据后发送本命令,用于触发参数保存及启用相关功能 下位机返回0x00
cmd=0x10 val=0x30 清除罗盘校准数据后发送本命令,确保上传的数据为传感器的原始数据 下位机返回0x00
cmd=0x10 val=0x31 发送完罗盘校准数据后发送本命令,用于触发参数保存及启用相关功能 下位机返回0x00
*/
typedef struct anoe0
{
    ano_head_t head;
    uint8_t cmd;
    uint16_t val;
    ano_tail_t tail;

} __packed parameter_cmd_t;

/**
 * 参数写入读取,为了方便,所有参数用float型
 * 本消息上位机发给下位机,下位机收到后要返回0x00
 */
typedef struct anoe1
{
    ano_head_t head;
    uint16_t par_id; // 参数的id
    float val;       // 参数的值
    ano_tail_t tail;
} __packed parameter_rw_t;

/**
 * 参数信息帧返回 下位机发给上位机
 * 上位机收到后不需要返回校验
 */
typedef struct anoe2
{
    ano_head_t head;
    uint16_t par_id;      // 本参数的ID
    uint8_t par_type;     // 本参数的数据类型
    uint8_t par_name[20]; // 参数名字
    uint8_t par_info[20]; // 参数说明
    ano_tail_t tail;
} __packed parameter_back_t;

/**
 * 设备信息返回
 */
typedef struct anoe3
{
    ano_head_t head;
    uint8_t dev_id;  // 设备信息
    uint16_t hw_ver; // 硬件版本
    uint16_t sw_ver; // 软件版本
    uint16_t bl_ver; // bootloader版本
    uint16_t pt_ver; // 通信协议版本
    uint8_t dev_name[12];
    ano_tail_t tail;
    /* data */
} __packed info_t;


/**
 * 固件升级
 * iap_cmd = 0x00 固件升级开始
 * 
 * iap_data = 0x0101 下位机判断固件非法
 * iap_data = 0x0102 下位机判断固件合法
 * iap_data = 0x0110 擦除flash命令
 * iap_data = 0x0111 擦除flash失败
 * iap_data = 0x0112 擦除flash成功
 * iap_data = 0x1001+BinFNum 第x帧写入失败
 * iap_data = 0x1002+BinFNum 第x帧写入成功
 * iap_data = 0x1010  固件发送完成
 * iap_data = 0x1011  固件校验失败
 * iap_data = 0x1012  固件校验成功
 * 
 * iap_cmd = 0x01 固件信息
 * 
 * iap_cmd = 固件内容
 */
typedef struct anof0
{
    ano_head_t head;
    uint8_t iap_cmd; // 升级命令
    uint16_t iap_data[256]; // 升级数据
    ano_tail_t tail;
    /* data */
} __packed firmware_update_t;

typedef struct cmd_flag
{
    uint8_t *check_arg; // 本次接收到的数据地址

    /*命令帧标志*/
    uint8_t C0;
    uint8_t C1;
    uint8_t C2;

    /* 参数命令读写标志 */
    uint8_t E0; // 参数命令
    uint8_t E1; // 参数写入,参数值读取返回
    uint8_t E2;
    uint8_t E3;

    uint8_t F0;//固件升级
    uint16_t do_it; // 针对e0的二级命令
} cmd_flag_t;

typedef struct AnoV8
{
    /******0x00回复校验*******/
    Check_t Check_d;
    /****0x01段*******/
    Ins_t Ins_d;
    Mag_t Mag_d;
    Angle_t Angle_d;
    Quaternion_t Quaternion_d;
    Height_t Height_d;
    Fc_mode_t Fc_mode_d;
    Speed_t Speed_d;
    Position_Offset_t Position_Offset_d;
    Wind_speed_t Wind_speed_d;
    tar_att_t tar_att_d;
    tar_speed_t tar_speed_d;
    RAD_t RAD_d;
    Vbat_t Vbat_d;
    extern_moude_sta_t extern_moude_sta_d;
    bri_rgb_t bri_rgb_d;

    /*****0x20段*******/

    Pwm_t Pwm_d;
    att_ctrl_t att_ctrl_d;

    /****0x40段********/

    Rc_t Rc_d;
    /******0xc0段********/
    cmd_c0_t cmd_c0_d;

    /******0xe0段******/
    info_t info_d;

    cmd_flag_t cmd_flag_d;
} __packed Ano_V8_t;

extern Ano_V8_t Ano_V8;

extern parameter_rw_t parameter_rw_g0;
extern struct cmd_g0 cmd_c0_g0;

extern uint8_t *cmd_c0_collection[cmd_number];

#define ANO_CMD_CHECK  Ano_V8.cmd_flag_d.C0=0x01

#define ANO_RESET_PARA __asm__("nop") // 复位所有参数
#define ANO_SAVE_PARA __asm__("nop") // 保存所有参数
#define ANO_CLEAR_ACCEL_CALI __asm__("nop") // 清除加速度校准数据
#define ANO_SAVE_ACCEL_CALI __asm__("nop") // 保存加速度校准数据
#define ANO_CLEAR_MAG_CALI __asm__("nop") // 清除罗盘校准数据
#define ANO_SAVE_MAG_CALI __asm__("nop") // 保存罗盘校准数据


void ano_send(void);
void ano_cmd_rev(uint8_t *arg);
#endif